﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.IO;
using System.Xml;
using System.Diagnostics;
using System.Windows.Forms;
/************************************************************************
To make the addin loaded, there are two solutions.
1. Copy the .addin file to the addins folders.
2. Add the path of the .addin file to the automation look in folder. 
    The change in UI is Tools|Options|Environment|Edd-in/Macros Security. 
    The corresponding register key is HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\AutomationOptions\LookInFolders

 
 Map the UI option settings to the register keys. (XP32 + VS2008)
 
-------------------------
** Visual Studio Setup **
-------------------------
1)

Visual Studio > Tools > Options > Projects and Solutions > VC++ Project Settings > 

>>> Add ;*.pde to "C/C++ File Extensions"
    The cosponding register key is
    [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\VC\VC_OBJECTS_PLATFORM_INFO\Win32\ToolDefaultExtensionLists] 
    "VCCLCompilerTool"="%VCCLCompilerTool%;*.pde" (The %xxx% stands for the existing value.)


>>> Add ;.pde to "Extensions To Include"
    The cosponding register key is
     [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\VC] 
    "Extensions To Include"= "%Extensions To Include%;.pde"

2)

Visual Studio > Tools > Options > Text Editor > File Extension

>>> Add PDE into the file extension list and associate it to Microsoft Visual C++

    Add the following register keys
 
     [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Default Editors\pde] 
    "Custom"="{8B382828-6202-11D1-8870-0000F87579D2}" 
    "Type"=dword:00000001 
     [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\FileExtensionMapping\pde] 
    @="{8B382828-6202-11D1-8870-0000F87579D2}" 
    "LogViewID"="{B2F072B0-ABC1-11D0-9D62-00C04FD9DFD9}" 


************************************************************************/


namespace VisualMicroSetupAction
{
    [RunInstaller(true)]
    public partial class AddinInstaller : Installer
    {
        /// <summary>
        /// Namespace used in the .addin configuration file.
        /// </summary> 
        private const String ExtNameSpace = "http://schemas.microsoft.com/AutomationExtensibility";

        /// <summary>
        /// 
        /// </summary>
        public AddinInstaller()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stateSaver"></param>
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);

            // Any change needs to be saved to state saver should be made here.
            // Note the difference of stateSaver and savedState.
            ApplyAddinSettingToVs(stateSaver);
            //RunResetAddIn();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="savedState"></param>
        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
            RemoveAddinSettingFromVs(savedState);
            //RunResetAddIn();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="savedState"></param>
        protected override void OnCommitted(IDictionary savedState)
        {
            base.OnCommitted(savedState);
            
        }

        public void RunResetAddIn()
        {
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo.FileName = "devenv.exe";

            //process.StartInfo.CreateNoWindow = true;
            //process.StartInfo.FileName = commandArray[0];
            process.StartInfo.Arguments = "/resetaddin Visual.Micro.Visual.Studio.Arduino.Helper";
            process.StartInfo.UseShellExecute = true;
            //process.StartInfo.RedirectStandardInput = true;
            //process.StartInfo.RedirectStandardOutput = true;
            //process.StartInfo.RedirectStandardError = true;
            process.Start();

            //devenv.exe
            //"/resetaddin Visual.Micro.Visual.Studio.Arduino.Helper"
        }

        /// <summary>
        /// Overrides Installer.Uninstall, which will be executed during uninstall process.
        /// </summary>
        /// <param name="savedState">The saved state.</param>
        public override void Uninstall(IDictionary savedState)
        {
            ////Debugger.Break();
            base.Uninstall(savedState);
            RemoveAddinSettingFromVs(savedState);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="savedState"></param>

        
        
        private void ApplyAddinSettingToVs(IDictionary savedState)
        {
            // Note: The flag value should keep consistent with the installed merge module.
            //bool isIntallingVM10_1 = true;

            // Parameters required to pass in from installer
            String installPath = this.Context.Parameters["InstallPath"];
            //not sure why installer is passing \\ on the end of the installpath
            if (installPath.EndsWith("\\\\"))
            {
                installPath=installPath.Substring(0,installPath.Length-1);
            }
            //String assemblyName = this.Context.Parameters["AssemblyName"];

            savedState.Add("InstallPath", installPath);

            // Populate .addin path and assembly path

            //if(isIntallingVM10_1)
            //{
            
            try
            {
                bool bAddConfigureForVS;

            //    if (bSucc)
            //    {
            
               /*
                Vs2005Helper vs2005 = new Vs2005Helper();
                    bool bAddConfigureForVS = vs2005.IsInstalled(); //&& !isIntallingVM10_1
                    savedState.Add("VS2005Installed", bAddConfigureForVS);
                    if (bAddConfigureForVS)
                    {
                        //String addinTargetPath = vs2005.GetAddinTargetPath();
                        //String targetFile = Path.Combine(addinTargetPath, addinConfigFileName);
                        //File.Copy(addinConfigFileFullName, targetFile, true);

                        //vs2005.AppendExtensionsToInclude();
                        vs2005.AddDefaultEditorsPDE();
                        vs2005.AddDefaultEditorsINO();
                        vs2005.AddLookInFolders(installPath);

                        // Save AddinFile to be used in Uninstall or Rollback
                        //savedState.Add("2005AddinFile", targetFile);

                        //MessageBox.Show(targetFile);
                    }
                                
                */


                    Vs2008Helper vs2008 = new Vs2008Helper();
                    bAddConfigureForVS = vs2008.IsInstalled(); //&& !isIntallingVM10_1
                    savedState.Add("VS2008Installed", bAddConfigureForVS);
                    if (bAddConfigureForVS)
                    {

                        String addinConfigFileName = "Visual.Micro.Visual.Studio.Arduino.2008.AddIn";
                        String addinAssemblyFileName = "Visual.Micro.Visual.Studio.Arduino.08.dll";
                        String addinConfigFileFullName = Path.Combine(installPath, addinConfigFileName);
                        String addinAssemblyFileFullName = Path.Combine(installPath, addinAssemblyFileName);
                        bool bSucc = UpdateTheAddinConfigFile(addinAssemblyFileFullName, addinConfigFileFullName);

                        //String addinTargetPath = vs2008.GetAddinTargetPath();
                        //String targetFile = Path.Combine(addinTargetPath, addinConfigFileName);
                        //File.Copy(addinConfigFileFullName, targetFile, true);

                        //vs2008.AppendExtensionsToInclude();
                        vs2008.AddDefaultEditorsPDE();
                        vs2008.AddDefaultEditorsINO();
                        vs2008.AddLookInFolders(installPath);

                        // Save AddinFile to be used in Uninstall or Rollback
                        //savedState.Add("2008AddinFile", targetFile);

                        //MessageBox.Show(targetFile);
                    }





                    Vs2010Helper vs2010 = new Vs2010Helper();
                    bAddConfigureForVS = vs2010.IsInstalled(); //&& isIntallingVM10_1
                    savedState.Add("VS2010Installed", bAddConfigureForVS);
                    if (bAddConfigureForVS)
                    {
                        String addinConfigFileName = "Visual.Micro.Visual.Studio.Arduino.2010.AddIn";
                        String addinAssemblyFileName = "Visual.Micro.Visual.Studio.Arduino.10.dll";
                        String addinConfigFileFullName = Path.Combine(installPath, addinConfigFileName);
                        String addinAssemblyFileFullName = Path.Combine(installPath, addinAssemblyFileName);
                        bool bSucc = UpdateTheAddinConfigFile(addinAssemblyFileFullName, addinConfigFileFullName);

                        //String addinTargetPath = vs2010.GetAddinTargetPath();
                        //String targetFile = Path.Combine(addinTargetPath, addinConfigFileName);
                        //File.Copy(addinConfigFileFullName, targetFile, true);

                        //vs2010.AppendExtensionsToInclude();
                        vs2010.AddDefaultEditorsPDE();
                        vs2010.AddDefaultEditorsINO();
                        vs2010.AddLookInFolders(installPath);

                        // Save AddinFile to be used in Uninstall or Rollback
                        //savedState.Add("2010AddinFile", targetFile);

                        //MessageBox.Show(targetFile);
                        //vs2010.RunResetAddIn();
                    }

                    // Modify the VS options if necessary.
                    // Note: Any action made here should be reverted during uninstallation.
                    
                //}
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                //MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="savedState"></param>
        private void RemoveAddinSettingFromVs(IDictionary savedState)
        {
            try
            {
                String installPath = (String)savedState["InstallPath"];
                // VS 2005
                bool b = (bool)savedState["VS2005Installed"];
                if (b)
                {
                    //String fileName = (String)savedState["2005AddinFile"];

                    //File.Delete(fileName);
                    Vs2005Helper vs2005 = new Vs2005Helper();
                    //vs2005.RemoveExtensionsToInclude();
                    vs2005.RemoveDefaultEditorsPDE();
                    vs2005.RemoveDefaultEditorsINO();
                    vs2005.RemoveLookInFolders(installPath);

                    //MessageBox.Show("2005");
                }

                // VS 2008
                b = (bool)savedState["VS2008Installed"];
                if (b)
                {
                    //String fileName = (String)savedState["2008AddinFile"];
                    
                    //File.Delete(fileName);
                    Vs2008Helper vs2008 = new Vs2008Helper();
                    //vs2008.RemoveExtensionsToInclude();
                    vs2008.RemoveDefaultEditorsPDE();
                    vs2008.RemoveDefaultEditorsINO();
                    vs2008.RemoveLookInFolders(installPath);

                    //MessageBox.Show("2008");
                }

                // VS 2010
                b = (bool)savedState["VS2010Installed"];
                if (b)
                {
                    //String fileName = (String)savedState["2010AddinFile"];
                    //File.Delete(fileName);
                    Vs2010Helper vs2010 = new Vs2010Helper();
                    //vs2010.RemoveExtensionsToInclude();
                    vs2010.RemoveDefaultEditorsPDE();
                    vs2010.RemoveDefaultEditorsINO();
                    vs2010.RemoveLookInFolders(installPath);

                    //MessageBox.Show("2010");
                }

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                //MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="addinAssemblyFileFullName"></param>
        /// <param name="addinConfigFileFullName"></param>
        /// <returns></returns>
        private bool UpdateTheAddinConfigFile(String addinAssemblyFileFullName, String addinConfigFileFullName)
        {
            try
            {
                // Modify the assembly path to be the actual install path.

                XmlDocument doc = new XmlDocument();
                doc.Load(addinConfigFileFullName);

                XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
                xnm.AddNamespace("def", ExtNameSpace);

                // Update node Extensibility/Addin/Assembly 
                XmlNode node = doc.SelectSingleNode("/def:Extensibility/def:Addin/def:Assembly", xnm);
                if (node != null)
                {
                    node.InnerText = addinAssemblyFileFullName;
                }

                // Update node Extensibility/ToolsOptionsPage/Assembly 
                node = doc.SelectSingleNode("/def:Extensibility/def:ToolsOptionsPage/def:Category/def:SubCategory/def:Assembly", xnm);
                if (node != null)
                {
                    node.InnerText = addinAssemblyFileFullName;
                }

                doc.Save(addinConfigFileFullName);
                //MessageBox.Show(addinConfigFileFullName); 
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                MessageBox.Show(ex.ToString()); 
                return false;
            }

            return true;
        }
    }
}
